﻿using ZeroBug.EasyFlow.Core;
using ZeroBug.EasyFlow.Machine;
using ZeroBug.EasyFlow.Motion;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using System.Runtime.CompilerServices;
using System.Threading;

namespace ZeroBug.EasyFlow.Steps
{
    public class CylinderOperateStep : IStep
    {
        public bool IsSingleRun { get; set; }
        public bool IgnoreChildren { get; set; }
        public string Icon { get; set; } = "Calendar";
        public int ChildrenIndex { get; set; }
        public Core.Step? NextStep { get; set; }

        VariableExpression isAsyncRun;
        VariableExpression cylinderNames;
        VariableExpression status;
        VariableExpression timeOut;
        public bool Compile(FlowBase flow, ZeroBug.EasyFlow.Core.Step step, out string errInfo)
        {
            errInfo = string.Empty;

            if (!step.Parameters.ContainsKey("CylinderNames"))
            {
                errInfo = "不存在CylinderNames变量";
                return false;
            }
            cylinderNames = step.Parameters["CylinderNames"];

            if (!step.Parameters.ContainsKey("Status"))
            {
                errInfo = "不存在Status变量";
                return false;
            }
            status = step.Parameters["Status"];

            if (step.Parameters.ContainsKey("AsyncRun"))
            {
                isAsyncRun = step.Parameters["AsyncRun"];
            }

            if (step.Parameters.ContainsKey("TimeOut"))
            {
                timeOut = step.Parameters["TimeOut"];
            }
            else
            {
                timeOut = new VariableExpression()
                {
                    ExpressionDealVarType = VariableType.Numeric,
                    Expressions = new List<string>()
                    {
                        "0"
                    }
                };
            }

            return true;
        }

        public object GetForm()
        {
            return new CylinderOperateStepForm();
        }

        public StepInfo GetInfo()
        {
            StepInfo info = new StepInfo();
            info.StepName = "CylinderOperate";
            info.Group = StepGroup.Motion;
            info.ImagePath = "pack://application:,,,/ZeroBug.EasyFlow.Step;component/Images/条件.png";
            return info;
        }

        public void OnChildrenEnter()
        {
        }

        public void OnChildrenLeave()
        {
        }

        public bool Prepare(FlowBase flow, ZeroBug.EasyFlow.Core.Step step, out string errInfo)
        {
            errInfo = string.Empty;
            return true;
        }

        public void RegisterVariables(FlowBase flow, ZeroBug.EasyFlow.Core.Step step)
        {
            if (flow.GetFlowManager().VariableManager.GetVariable($"{step.Description}.Completed") == null)
            {
                Variable taskCompleted = new Variable($"{step.Description}.Completed", string.Empty, VariableType.Boolean);
                taskCompleted.GetCurrentValues = () =>
                {
                    return new string[] { task.IsCompleted.ToString() };
                };
                flow.GetFlowManager().VariableManager.AddVariable(taskCompleted, VariableFrom.Local);
            }
        }

        Task? task;
        public StepResult Run(FlowBase flow, ZeroBug.EasyFlow.Core.Step step, out string errInfo)
        {
            errInfo = "";

            if (isAsyncRun != null && Convert.ToBoolean(isAsyncRun.GetEquivalent()[0]))
            {
                while (task?.IsCompleted == false)
                {
                    Thread.Sleep(20);
                }
                task = Task.Run(() =>
                {
                    method();
                });
            }
            else
                method();

            return StepResult.Success;
        }
        private void method()
        {
            Variable cylinders = cylinderNames.GetEquivalent();
            Variable sts = status.GetEquivalent();
            for (int i = 0; i < cylinders.Count; i++)
            {
                Cylinder? c = LocalMachine.Services.GetService<MachineResource<Cylinder, IDigitalIO>>()?.Value?[cylinders[i]];
                if (Convert.ToBoolean(sts[i]))
                    c.On();
                else
                    c.Off();
            }
            if (false)
            {
                for (int i = 0; i < cylinders.Count; i++)
                {
                    Cylinder? c = LocalMachine.Services.GetService<MachineResource<Cylinder, IDigitalIO>>()?.Value?[cylinders[i]];
                    if (Convert.ToBoolean(sts[i]))
                        c.WaitOn(Convert.ToInt32(timeOut.GetEquivalent()[0]));
                    else
                        c.WaitOff(Convert.ToInt32(timeOut.GetEquivalent()[0]));
                }
            }

            Random random = new Random();
            Thread.Sleep(random.Next(1000, 2000));
        }

        public string GetTip(Core.Step step)
        {
            return "";
        }

        public (SerializableDictionary<string, VariableExpression>, List<VariableJudge>) GetParametersAndConditions()
        {
            throw new NotImplementedException();
        }

        public void UnRegisterVariables(FlowBase flow, Core.Step step)
        {
        }
    }
}
